package com.terrynoya.fight.animations
{
	import com.terrynoya.coreLib.MHashMap;
	import com.terrynoya.fight.emuns.ClsnType;
	import com.terrynoya.fight.io.FileSystem;
	import com.terrynoya.fight.io.TextFile;
	import com.terrynoya.fight.io.TextSection;
	import com.terrynoya.geom.MVector2D;
	
	import flash.geom.Rectangle;
	
	import spark.primitives.Rect;

	public class AirParser implements IAirInfo
	{
		public static const ACTION_REG:RegExp = /^\s*Begin Action (-?\d+)/;
		public static const CLSN_REG:RegExp = /Clsn([12])(Default)?:\s*(\d+)/;
		public static const CLSN_LINE_REG:RegExp = /Clsn([12])?\[(-?\d+)\]\s*=\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*(-?\d+)/;
		
		private var _animations:MHashMap;
		
		public static const NONE_MARK:int = 0;
		public static const CLSN_TITLE:int = 1;
		public static const CLSN_LINE:int = 2;
		public static const SPRITE_MARK:int = 3;
		
		public function AirParser()
		{
			
		}
		
		public function get animations():MHashMap
		{
			return _animations;
		}

		public function parse(input:String):void
		{
			this._animations = new MHashMap();
			
			var file:TextFile = FileSystem.build(input);
			for (var i:int = 0; i < file.sections.length; i++) 
			{
				var section:TextSection = file.sections[i];
				if(ACTION_REG.test(section.title)) 
				{
					var ani:Animation = this.createAnimation(section);
					this._animations.put(ani.id,ani);
				}
			}
		}
		
		public function getAnimation(id:int):IAnimation
		{
			return this._animations.getValue(id);
		}
		
		public function hasAnimation(id:int):Boolean
		{
			return this._animations.containsKey(id);
		}
		
		private function createAnimation(section:TextSection):Animation
		{
			var lastLineType:int = NONE_MARK;
			var lstClsnType:int = ClsnType.None;
			var defaultClsnList:Array = new Array();
			var clsnList:Array = new Array();
			var actionId:int = this.getActionId(section.title);
			var ani:Animation = new Animation(actionId);
			var elements:Array = new Array();
			
			var isDefaultClsn:Boolean = false;
			var startTick:int = 0; 
			
			for (var i:int = 0; i < section.lines.length; i++) 
			{
				var data:String = section.lines[i];
				if(CLSN_REG.test(data))
				{
					var isDefault:Boolean = this.isDefaultClsn(data);
					this.getClsnTitleType(data);
					if(isDefault)
					{
						defaultClsnList = new Array();
						isDefaultClsn = true;
					}
					else
					{
						isDefaultClsn = false;
					}
					lastLineType = CLSN_TITLE;
				}
				else if(CLSN_LINE_REG.test(data))
				{
					var match:Array = data.match(CLSN_LINE_REG);
					var index:int = match[2];
					var clsn:Clsn = this.getRect(data);
					if(isDefaultClsn)
					{
						defaultClsnList[index] = clsn;
					}
					else
					{
						clsnList.push(clsn);
					}
					lastLineType = CLSN_LINE;
				}
				else if(data == "Loopstart")
				{
					ani.loopStartId = elements.length;
				}
				else
				{
					var ele:AnimationElement = this.getElement(data,startTick);
					ele.id = elements.length;
					if(isDefault || lastLineType == SPRITE_MARK)
					{
						ele.clsns = defaultClsnList.concat(clsnList);
					}
					else
					{
						ele.clsns = clsnList.concat(defaultClsnList);
					}
					elements.push(ele);
					clsnList = new Array();
					lastLineType = SPRITE_MARK;
					if(ele.ticks == -1)
					{
						startTick = -1;
					}
					else
					{
						startTick += ele.ticks;
					}
				} 
			} 
			ani.setElements(elements);
			return ani;
		}
		
		private function getClsnTitleType(data:String):int
		{
			var match:Array = data.match(CLSN_REG);
			var val:int = int(match[1]);
			if(val == 1)
			{
				return ClsnType.Type1Attack;
			}
			else if(val == 2)
			{
				return ClsnType.Type2Normal;
			}
			else
			{
				return ClsnType.None;	
			}
		}
		
		private function isDefaultClsn(data:String):Boolean
		{
			var match:Array = data.match(CLSN_REG);
			if(match == null || match.length < 3)
			{
				return false;
			}
			var str:String = match[2];
			return str == "Default";
		}
		
		private function getElement(txt:String,startTick:int):AnimationElement
		{
			var arr:Array = txt.split(",");
			var ele:AnimationElement = new AnimationElement();
			var id:SpriteId = new SpriteId();
			id.groupId = int(arr[0]);
			id.imageId = int(arr[1]);
			ele.spriteId = id;
			ele.offset = new MVector2D(int(arr[2]),int(arr[3]));
			ele.ticks = int(arr[4]);
			ele.startTick = startTick;
			return ele;
		}
		
		private function getRect(txt:String):Clsn
		{
			var match:Array = txt.match(CLSN_LINE_REG);
			var clsnType:int = match[1];
			var index:int = match[2];
			var a:int = int(match[3]);
			var b:int = int(match[4]);
			var c:int = int(match[5]);
			var d:int = int(match[6]);
			
			var x:int = Math.min(a,c);
			var y:int = Math.min(b,d);
			var w:int = Math.abs(a-c);
			var h:int = Math.abs(b-d);
			var rect:Rectangle = new Rectangle(x,y,w,h);
			var clsn:Clsn = new Clsn(clsnType,rect);
			return clsn;
		}
		
		private function getActionId(title:String):int
		{
			var matched:Array = title.match(ACTION_REG);
			var actionId:int = int(matched[1]);
			return actionId;
		}
	}
}